package com.simple.protogen.enums;

import cn.hutool.core.lang.Pair;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import tools.MessageManager;

@Slf4j
public enum EGenCode {

    MsgIds() {
        @Override
        protected void doGenCode() throws Exception {
            // 执行sh脚本
            String genProtoPath = Path.of(System.getProperty("user.dir"), "msg").toString();

            String cdCommand = String.format("cmd /c cd /d %s && bash genProto.sh", genProtoPath);
            executeCommand(cdCommand);

            // 消息数
            Map<Class<?>, Integer> msgClazz2MsgCodeMap = MessageManager.getMsgClazz2MsgIdMap();
            log.info("total msg count={}", msgClazz2MsgCodeMap.size());

            // 生成代码
            super.doGenCode();
        }

        @Override
        protected List<Map<Object, Object>> getResultList() {
            // 提前做一些初始化
            MessageManager.init();

            Map<Class<?>, Integer> msgClazz2MsgIdMap = MessageManager.getMsgClazz2MsgIdMap();

            List<Class<?>> clazzList = Lists.newArrayList(msgClazz2MsgIdMap.keySet());
            clazzList.sort(Comparator.comparingInt(MessageManager::getMsgIdByMsgClazz));

            List<Pair<String, Integer>> clazzName2MsgIdList = clazzList.stream()
                    .map(c -> Pair.of(c.getSimpleName(), MessageManager.getMsgIdByMsgClazz(c))).collect(Collectors.toList());

            List<Map<Object, Object>> results = Lists.newArrayList();
            for (Pair<String, Integer> pair : clazzName2MsgIdList) {
                results.add(Map.of("clazzName", pair.getKey(), "msgId", pair.getValue()));
            }

            return results;
        }
    },
    ;

    protected void doGenCode() throws Exception {
        List<Map<Object, Object>> results = getResultList();
        Map<String, Object> valueMap = Maps.newHashMap();
        valueMap.put("results", results);

        // 生成准备
        String useTemplatePath = getUseTemplatePath();
        String useTemplateName = this.name() + ".ftl";
        String outPath = getOutPath();
        String genPackageName = getGenPackageName();
        String genFileName = this.name() + ".java";

        // 参数准备
        final String ENCODING = "UTF-8";

        // 代码生成
        TemplateLoader loader = new FileTemplateLoader(new File(useTemplatePath));
        Configuration cfg = new Configuration();
        cfg.setTemplateLoader(loader);
        cfg.setEncoding(Locale.getDefault(), ENCODING);

        Template template = cfg.getTemplate(useTemplateName, ENCODING);
        template.setOutputEncoding(ENCODING);

        File filePath = new File(outPath, genPackageName.replace(".", File.separator));
        if (!filePath.exists()) {
            filePath.mkdir();
        }

        File targetFile = new File(filePath, genFileName);
        if (targetFile.exists()) {
            targetFile.delete();
        }

        template.process(valueMap, new OutputStreamWriter(new FileOutputStream(targetFile, false), ENCODING));


        log.info("生成文件成功: {}", targetFile.getAbsolutePath());
    }

    protected String getUseTemplatePath() {
        String PATH = System.getProperty("user.dir");
        return Path.of(PATH, "tools", "protogen", "src", "main", "resources", "template").toString();
    }

    protected String getOutPath() {
        String PATH = System.getProperty("user.dir");

        return Path.of(PATH, "common", "src", "main", "java").toString();
    }

    protected String getGenPackageName() {
        return "msg";
    }

    public void executeCommand(String cmd) throws Exception {
        // 执行系统命令
        Process process = Runtime.getRuntime().exec(cmd);

        int waitForCode = process.waitFor();
        int exitCode = process.exitValue();

        log.info("run cmd={} end! waitForCode={}, exitCode={}", cmd, waitForCode, exitCode);

        // 获取命令的输出流
        InputStream inputStream = process.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        // 逐行读取输出并打印
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }

        System.out.println();
    }

    // 需要重写的
    // 模板需要数据
    protected abstract List<Map<Object, Object>> getResultList();

    public static void genCode() {
        for (EGenCode e : values()) {
            try {
                e.doGenCode();
            } catch (Exception ex) {
                log.error("生成文件{}失败!!! error=", e.name(), ex);
            }
        }

        log.info("genCode ok.");
    }
}
